#pragma once

#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <unistd.h>
#include <string>


const std::string pathname = "/home/gjk";
int projId = 0x6666;
int msize = 4096;
mode_t mode = 0600;

std::string ToHex(key_t k)
{
    char buffer[64];
    snprintf(buffer, sizeof(buffer), "0x%x", k);
    return buffer;
}

class ShareSMemory
{
public:
    ShareSMemory() : _key(-1), _shmid(-1), _addr(nullptr)
    {}

    // 获取key
    void GetKey()
    {
        _key = ::ftok(pathname.c_str(), projId);
        if (_key < 0)
        {
            std::cerr << "ftok error" << std::endl;
            exit(-1);
        }
        std::cout<<"GetKey done"<<std::endl;
    }

    // 创建共享内存
    void CreateSMemory()
    {
        _shmid = ::shmget(_key, msize, IPC_CREAT | IPC_EXCL | mode);
        if (_shmid < 0)
        {
            std::cerr << "shmget error" << std::endl;
            exit(-2);
        }
        std::cout<<"CreateSMemory done"<<std::endl;
    }

    // 已经创建好,直接获取共享内存
    void GetSMemory()
    {
        _shmid = ::shmget(_key, msize, IPC_CREAT | mode);
        if (_shmid < 0)
        {
            std::cerr << "shmget error" << std::endl;
            exit(-2);
        }
        std::cout<<"GteSMemory done"<<std::endl;
    }

    //挂在共享内存到自己的地址空间
    void AttachSMemory()
    {
        _addr = ::shmat(_shmid, nullptr, 0);
        if ((long long)_addr < 0)
        {
            std::cerr << "attch error" << std::endl;
            exit(-3);
        }
        std::cout<<"AttachSMemory done"<<std::endl;
    }


    //去关联
    void DetachSMemory()
    {
        ::shmdt(_addr);
        std::cout<<"DetachSMemory done"<<std::endl;
    }

    void* GetAddr()
    {
        return _addr;
    }

    //删除共享内存
    void DeleteSMemory()
    {
        ::shmctl(_shmid,IPC_RMID,nullptr);
        std::cout<<"DeleteSMemory done"<<std::endl;
    }

    ~ShareSMemory()
    {}

private:
    key_t _key;
    int _shmid;
    void *_addr;
};


ShareSMemory ssm;


struct data
{
    char status[32];//消息的状态
    char lasttime[48];//消息最后输出的时间
    char message[1024];//消息
};

